<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      class MyPromise {
        state = "pending";
        result = undefined;
        handlers = [];

        constructor(executor) {
          const resolve = (data) => {
            this.#changeState("fulfilled", data);
          };

          const reject = (reason) => {
            this.#changeState("rejected", reason);
          };

          try {
            executor(resolve, reject);
          } catch (error) {
            reject(error);
          }
        }

        // 改变状态
        #changeState(state, data) {
          if (state === "pending") return;
          this.state = state;
          this.result = data;
          this.#run();
        }

        #run() {
          if (this.state !== "pending") return;
          while (this.handlers.length) {
            const { onFulfilled, onRejected, resolve, reject } =
              this.handlers.shift();
            if (this.state === "fulfilled") {
              if (typeof onFulfilled === "function") {
                onFulfilled(this.result);
              }
            } else {
              if (typeof onRejected === "function") {
                onRejected(this.result);
              }
            }
          }
        }

        // then
        then(onFulfilled, onRejected) {
          return new Promise((resolve, reject) => {
            this.handlers.push({
              onFulfilled,
              onRejected,
              resolve,
              reject,
            });
            this.#run();
          });
        }
      }

      // 测试用例
      const p = new MyPromise((resolve, reject) => {
        setTimeout(() => {
          resolve("111");
        }, 1000);
      });

      p.then(
        (res) => {
          console.log("res-1", res);
        },
        (err) => {
          console.log("err-1", err);
        }
      );

      // p.then(
      //   (res) => {
      //     console.log("res-2", res);
      //   },
      //   (err) => {
      //     console.log("err-2", err);
      //   }
      // );
    </script>
  </body>
</html>
